<?php
require 'helper_functions.php';

function match_triple(&$q, $vars, $data_triples)
{
	foreach($data_triples as $t)
	{
		$ft = array('s'=>$t['s']['uri'], 'p' =>$t['p'], 'o' => (isset($t['o']['val']))? $t['o']['val'] : $t['o']['uri'] );
		
		if($q['s']==$t['s']['uri'] || in_array('s',$vars))
		{
			if($q['p']==$t['p'] || in_array('p',$vars))
			{
				if($q['o']==$ft['o'] || in_array('o',$vars))
				{
					//there's a match
					$match = array();
					foreach($vars as $v)
					{
						$match[$q[$v]]=$ft[$v];
						
						$q[$v]=$ft[$v];
					}
					return $match;
				}
			}
		}
	}
	
	//no match
	return false;
}

/*
triples_to_resources($rdfxml)

 transforms RDF/XML to a php associative array version 
of the RDF/JSON format specified at http://lpag-wiki.talis.com/wiki/RDF_JSON_Brainstorming
with the exception that the associative array of resources occurs under a "resources" key instead of at the same level as "prefixes"
*/

function triples_to_resources($triples, $namespaces=array())
{
	$inverted_namespaces = array_flip($namespaces);
	
	// this is the rdf/php data object
	$rdf_php = array();		

	foreach($triples as $t)
	{
		$o = array();
		if(isset($t['o']['uri']))
		{
			$o['type'] = 'uri';
			$o['value'] = $t['o']['uri'];
		}
		elseif(isset($t['o']['val']))
		{
			$o['type'] = 'literal';
			$o['value'] = $t['o']['val'];
		}
		
		// get a prefixed version of the predicate uri if available
		$p_parts =  split_uri($t['p']);
		
		$p = (isset($inverted_namespaces[$p_parts[0]]))? $inverted_namespaces[$p_parts[0]].':'.$p_parts[1] : $t['p'];
		
		if(isset($t['o']['lang'])) $o['lang'] = $t['o']['lang'];
		if(isset($t['o']['dt'])) $o['datatype'] = $t['o']['dt'];
		$rdf_php[$t['s']['uri']][$p][]=$o;
	}
	return $rdf_php;
}


function get_subjects_and_objects($triples)
{
	$subs = array();
	foreach($triples as $t)
	{
		$subs[]=$t['s'];
		$subs[]=$t['o'];
	}
	
	return array_unique($subs);
}

function triple_match($triple, $triples,$ignore_variables=false)
{
	if($ignore_variables===false) foreach($triple as $k => $v) $triple[$k] = (erdf_var_name($v))? 0 : $v ; 
	else foreach($triple as $k => $v) $triple[$k] = (erdf_var_name($v))? erdf_var_name($v) : $v ; 
	extract($triple);
	$matches = array();
	foreach($triples as $t)
	{
		if(
			($t['s']==$s || !$s) &&
			($t['p']==$p || !$p) &&
			($t['o']==$o || !$o)
			)
			{
				$matches[] = $t;
			}
		
	}
	return $matches;
}


function assign_variables($query_triples, $data_triples)
{
	$results = array();
	
	$subjects_and_objects = get_subjects_and_objects($query_triples);
	
	//get all the variable subjects from the template
	$variable_subjects = array_filter($subjects_and_objects, "erdf_var_name");
	foreach($variable_subjects as $s)
	{
		
		$matching_values = array(); //this will be a 2d array of arrays of values 
		// iterate over  the template triples that have a matching subject
		foreach($query_triples as $triple) 
		{
			if($triple_key = triple_has_resource($triple,$s)) 
			{
				//get all data triples that could match this query triple
				$matches = triple_match($triple, $data_triples);
				if(count($matches)==1) //there's only one thing it could be
				{
					$results[substr(erdf_var_name($s),1)] = $matches[0][$triple_key];
					$matching_values[] = array($matches[0][$triple_key]);
					$query_triples =  fill_in_blanks(erdf_var_name($s), $matches[0][$triple_key], $query_triples);
				}
				else if(count($matches)>1)//need to figure out which it is from context
				{
					$matching_values[] = values_by_key($matches, $triple_key); //this returns an array of values
				}
				else
				{
					//error_log("There are no matches in the data for ".print_r($triple));
				}
			}
		}	

		//
		if( !empty($matching_values) )
		{
			//find matches across the graph
			$values = array_rdiff($matching_values);
			if(count($values) >1 )
			{
				error_log("there are more than one possible matches for {$s}");
			}
			else if(count($values)==1)
			{
				$query_triples =  fill_in_blanks(erdf_var_name($s), $values[0], $query_triples);
				$results[substr(erdf_var_name($s),1)] = $values[0];
			}
		}

	}
	
	return $results;
}

function values_by_key($triples, $key)
{
	$results = array();
	foreach($triples as $t)
	{
		$results[]=$t[$key];
	}
	return $results;
}

function fill_in_blanks($k,$v, $query_triples)
{
	$x = 0;
	foreach($query_triples as $qt)
	{
		foreach($qt as $qtk =>$qtv)
		{
			if(erdf_var_name($qtv)==$k) $query_triples[$x][$qtk] = $v;
		}
		$x++;
	}
	return $query_triples;
}


?>